home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / pcl / sptmbr16.lha / notes.text < prev    next >
Text File  |  1992-12-07  |  14KB  |  317 lines

  1. These notes correspond to the "August 5 92 PCL" version of PCL.
  2.  
  3.   This version of PCL is much closer than previous versions of PCL
  4. to the metaobject protocol specified in "The Art of the Metaobject Protocol", 
  5. chapters 5 and 6, by Gregor Kiczales, Jim des Riveres, and Daniel G. Bobrow.
  6.  
  7.  
  8. [Please read the file may-day-notes.text also.  Most of that file still applies.]
  9.  
  10. Support for structures
  11.   You can use structure-class as a metaclass to create new classes.
  12.   Classes created this way create and evaluate defstruct forms which
  13.   have generated symbols for the structure accessors and constructor.
  14.   The generated symbols are used by the primary slot-value-using-class
  15.   methods and by the primary allocate-instance method for structures.
  16.   Defmethod optimizes usages of slot-value (when no user-defined 
  17.   slot-value-using-class methods exist) into direct calls of the
  18.   generated symbol accessor, which the compiler can then optimize further.
  19.   Even when there are user-defined methods on slot-value-using-class,
  20.   PCL does a variety of optimizations.
  21.   
  22.   If your implementation's version of the *-low.lisp file
  23.   contains definitions of certain structure functions (see the end of
  24.   low.lisp, cmu-low.lisp, lucid-low.lisp, and kcl-low.lisp), then
  25.   structure classes are supported for all defstructs.  In this case,
  26.   structure classes are created automatically, when necessary.
  27.  
  28. New Classes:
  29. structure-class
  30. structure-object
  31. slot-class
  32. slot-object
  33. structure-direct-slot-definition
  34. structure-effective-slot-definition
  35.  
  36. Improvements to slot-access
  37.   Optimization for slot-value outsize of defmethod
  38.   Optimization for slot-value inside of defmethod, but not of a specialized parameter.
  39.   Optimizations that work even when there are :around methods
  40.   on slot-value-using-class.
  41.  
  42. New types: 
  43.    `(class ,class-object)
  44.    `(class-eq ,class-object)
  45.  
  46. New specializer class: class-eq-specializer
  47.   Every class has a class-eq specializer which represents all
  48.   the direct instances of that class.
  49.   This is useful in *subtypep.  For example, here is the way 
  50.   generic-function initialization checks that the method-class is valid:
  51.    (and (classp method-class)
  52.     (*subtypep (class-eq-specializer method-class)
  53.            (find-class 'standard-method)))
  54.   If you want to define methods having class-eq specializers,
  55.   see "Initialization of method metaobjects".  The default behavior of PCL
  56.   is to disallow this.
  57.  
  58. compute-applicable-methods-using-types
  59.  
  60. caching improvements
  61.  
  62. no magic-generic-functions list
  63.   This simplifies some things, but complicates some other things.
  64.   I wanted to support user-defined classes which are their own metaclass.
  65.   You can now do:
  66. (defclass y (standard-class) ())
  67. (defmethod validate-superclass ((c y) (sc standard-class)) t)
  68. (defclass y (standard-class) () (:metaclass y))
  69.  
  70. method-function changes (see the comments for make-method-lambda, below)
  71.  
  72. final dfuns
  73.  
  74. -------------------------
  75.  
  76. gfs which obey AMOP ch 6
  77.   accessor-method-slot-definition
  78.   add-dependent
  79.   add-direct-method
  80.   add-direct-subclass
  81.   add-method
  82.   allocate-instance
  83.   compute-class-precedence-list
  84.   compute-default-initargs
  85.   compute-discriminating-function  
  86.   compute-effective-slot-definition
  87. [Note: compute-effective-slot-definition relys on 
  88.  compute-effective-slot-definition-initargs and effective-slot-definition-class.
  89.  compute-effective-slot-definition-initargs is quite useful, but is not in
  90.  AMOP ch 6.]
  91.   compute-slots
  92.   direct-slot-definition-class
  93.   effective-slot-definition-class
  94.   ensure-class
  95.   ensure-class-using-class
  96.   ensure-generic-function
  97.   ensure-generic-function-using-class
  98.   eql-specializer-object
  99.   extract-lambda-list
  100.   extract-specializer-names
  101.   finalize-inheritance
  102.   find-method-combination
  103.   funcallable-standard-instance-access
  104.   {generic-function-method-class, generic-function-method-combination,
  105.    generic-function-lambda-list, generic-function-methods, generic-function-name}
  106.   intern-eql-specializer
  107.   make-instance
  108.   make-method-lambda
  109.   map-dependents
  110.   {method-function, method-generic-function, method-lambda-list,
  111.    method-specializers, method-qualifiers}
  112.   {class-default-initargs, class-direct-default-initargs, class-direct-slots,
  113.    class-direct-subclasses, class-direct-superclasses, class-finalized-p,
  114.    class-name, class-precedence-list, class-prototype, class-slots}
  115.   {slot-definition-allocation, slot-definition-initargs, slot-definition-initform,
  116.    slot-definition-initfunction, slot-definition-name, slot-definition-type}
  117.   {slot-definition-readers, slot-definition-writers}
  118.   {slot-definition-location}
  119.   remove-dependent
  120.   remove-direct-method
  121.   remove-direct-subclass
  122.   remove-method
  123.   set-funcallable-instance-function
  124.   (setf slot-value-using-class)
  125.   slot-boundp-using-class
  126.   slot-makunbound-using-class
  127.   specializer-direct-generic-functions
  128.   specializer-direct-methods
  129.   standard-instance-access
  130.   update-dependent
  131.  
  132. gfs which DO NOT obey AMOP ch 6
  133.  
  134. compute-applicable-methods
  135. compute-applicable-methods-using-classes
  136.   Handles class-eq specializers without signalling an error.  
  137.   But see "Initialization of method metaobjects", below.
  138.  
  139. compute-effective-method
  140.   Returns only one value. 
  141.  
  142. generic-function-argument-precedence-order
  143.   Not yet defined.  Can get this information from the arg-info structure.
  144.  
  145. generic-function-declarations
  146.   Not yet defined.
  147.  
  148. reader-method-class
  149.   Not yet defined.  Some bootstrapping considerations are involved, 
  150.   but adding this will not be very hard.
  151.  
  152. (setf class-name)
  153.   Currently just a writer method.  Does not call reinitialize-instance or
  154.   (setf find-class).
  155.  
  156. (setf generic-function-name)
  157.   Currently just a writer method.  Does not call reinitialize-instance.
  158.  
  159. writer-method-class
  160.   Not yet defined.  Some bootstrapping considerations are involved, 
  161.   but adding this will not be very hard.
  162.  
  163. ---------------------------
  164.  
  165. Initialization of method metaobjects
  166.   The following methods are defined:
  167.     legal-qualifiers-p (method standard-method) qualifiers
  168.     legal-lambda-list-p (method standard-method) lambda-list
  169.     legal-specializers-p (method standard-method) specializers
  170.     legal-method-function-p (method standard-method) function
  171.     legal-documentation-p (method standard-method) documentation
  172.  
  173.     legal-specializer-p (method standard-method) specializer
  174.  
  175.   You can override them if you want.
  176.   The method for legal-specializers-p calls legal-specializer-p
  177.   on each specializer.
  178.   The method for legal-specializer-p allows any kind of specializer
  179.   when the variable *allow-experimental-specializers-p* is t
  180.   (this variable is initially nil).
  181.  
  182. ---------------------------
  183. Optimizations on slot-value
  184.   Outside of a defmethod when define-compiler-macro is not implemented
  185.   or the slot-name is not constant, or
  186.   Inside a defmethod when the slot-name is not a constant:
  187. (1)   no optimization of slot-value, slot-value-using-class is called.
  188.       slot-value-using-class has a special dfun, though, which calls
  189.       the slot's slot-definition-reader-function.  This function is
  190.       a result of get-accessor-method-function.
  191.   Outside of a defmethod when define-compiler-macro is implemented and
  192.   the slot-name is a constant, or
  193.   Inside a defmethod when the slot-name is a constant but the object is 
  194.   not either (the value of a parameter specialized to a subclass of structure-object
  195.   for which no user-defined slot-value-using-class methods apply at defmethod time), 
  196.   or (the value of a parameter specialized to a subclass of standard-object).
  197. (2)   PCL arranges to call an automatically created generic function
  198.       which has one method: a reader method defined on class slot-object.
  199.   Inside a defmethod when the slot-name is a constant and the object 
  200.   is (the value of a parameter specialized to a subclass of structure-object
  201.   for which no user-defined slot-value-using-class methods apply).
  202. (3)   The slot-value form is converted to a call of the structure slot's 
  203.       accessor function, which the compiler can then optimize further.
  204.   Inside a defmethod when the slot-name is a constant and the object 
  205.   is (the value of a parameter specialized to a subclass of standard-object).
  206. (4)   The access requires two arefs, a call to (typep x 'fixnum), and a call to eq,
  207.       in the best case.  If user defined slot-value-using-class methods apply
  208.       at slot-value execution time, or the slot is unbound, the unoptimized 
  209.       slot-value function (1) is called.  This was in May Day PCL; what is new here
  210.       is that the PV (permutation vector) is looked up at defmethod load time
  211.       rather than at run time, if the effective method is cached.
  212.  
  213. Generic functions containing only accessor methods for which no user-defined
  214. methods on slot-value-using-class apply and which involve only standard-classes:
  215.       A special dfun is called: one-class, two-class, one-index, or n-n.
  216.       These were all in May Day PCL.
  217. Generic functions excluded by the above, which contain accessor methods:
  218.       In place of each accessor method's method-function, a function returned by
  219.       get-accessor-method-function is used.
  220.  
  221. get-accessor-method-function (gf type class slotd) ; type is reader, writer, or boundp.
  222.   If there is only one applicable method,
  223.       (This method will be the system supplied one)
  224.       the function that is returned is optimized for the current state of the
  225.       class.  When the class changes, it must be recomputed.
  226.   otherwise,
  227.       a secondary dispatch function for slot-value-using-class is computed
  228.       (using what is known about the types of the arguments) and converted 
  229.       into an accessor function.
  230.  
  231. get-secondary-dispatch-function (gf methods types &optional method-alist wrappers)
  232.   The types argument describes what is known about the types of the arguments.
  233.   Method-alist is used (when supplied) to do things like replace the
  234.   standard slot-value-using-class method function with a function optimized
  235.   for what is known about the arguments.
  236.   Wrappers (when supplied) means that the resulting function is guaranteed to
  237.   be called only whith those wrappers.  Make-effective-method-function calls
  238.   the generic-function method-function-for-caching with method-alist and
  239.   wrappers to get a optimized method function.  (PV lookup is done at the time
  240.   method-function-for-caching is called).
  241.  
  242. compute-applicable-methods:  Here I tried to stick with the MOP.
  243.   The function cache-miss-values looks at the second value of the result of 
  244.   compute-applicable-methods-using-classes.  If this value is null, we aren't 
  245.   supposed to cache the result of camuc.  So we don't.  Instead we cache a 
  246.   result of (default-secondary-dispatch-function gf), which in turn calls 
  247.   compute-applicable-methods each time it is called.
  248. ---------------------------
  249.  
  250. To do:
  251.  
  252. Problem: sometimes there is no need to call a gf's dfun: the emf that is invoked
  253.          can be cached in the caller's method closure.
  254. 1.  In expand-defmethod-internal, optimize calls to generic-functions.
  255.   Add the support for this optimization.
  256.  
  257. 2.   [When CMUCL improves its setf handling, remove the comment in
  258.    the file macros.lisp beginning the line ";#+cmu (pushnew :setf *features*)"]
  259.  
  260.  
  261.  
  262. --------------
  263. 1) Generalize expand-defmethod-internal so that it can be used for non-defmethod
  264. code.  Maybe by (a) having a parameter that says whether it is being called by 
  265. defmethod, and (b) using the techniques used by the series package (shadowing 
  266. defun and some others, making the shadowed definitions call e-d-i, making it 
  267. easy for people to do the relevant package modifications)
  268.  
  269. 2) Extending generic-functions by allowing the user at defgeneric time to supply
  270. the name of a function which will be supplied (by the system) with a definition
  271. which will return equivalent results to those returned by the generic function,
  272. but which will (in some cases) have less checking than the generic function.
  273. One-class, two-class, and one-index gf dfuns will map to a result of 
  274. get-optimized-std-accessor-method-function, checking gf dfuns will map to their
  275. function, and any other dfun will remain the same.
  276.  
  277. 3) Extending expand-defmethod-internal to optimize calls to generic-functions.
  278. There are a variety of possibilities that need to be considered; one of them
  279. will be to arrange to call the optimized functions produced by (2) when it
  280. is known to be safe.  
  281. ----------------------------------------------------------------------
  282. ----------------------------------------------------------------------
  283.  
  284. Here is how PCL uses the compiler at run time:
  285.  
  286.   The only function that uses COMPILE is COMPILE-LAMBDA, defined in
  287. low.lisp.  See the code for some comments on how it works.
  288.  
  289. There are basically three uses of COMPILE-LAMBDA: 
  290.   for creating discriminator functions (March 92 PCL creates discriminator 
  291.     functions via lap code, September 16 PCL creates lisp code directly -
  292.     it is easier to read the Sept PCL code.  Both versions invoke 
  293.     COMPILE-LAMBDA in a similar manner.)  Precompiling of discriminator
  294.     functions is done via the macro precompile-dfun-constructors.
  295.  for creating constructor functions (This is in Sept PCL only; 
  296.     see fast-init.lisp for more information).  Precompiling of 
  297.     constructor functions is done via the macro precompile-iis-functions.
  298.  for creating the internal functions used by GET-FUNCTION (defined in 
  299.     fngen.lisp.  Refer to the September 16 92 PCL version because it has 
  300.     better documentation on GET-FUNCTION.)  Precompiling of these functions
  301.     is done by precompile-function-generators.
  302.  
  303. Precompiling of all three kinds of functions is done by
  304. PRECOMPILILE-RANDOM-CODE-SEGMENTS (defined in low.lisp).
  305.  
  306. There are two uses of GET-FUNCTION (actually GET-FUNCTION1):
  307.   to create effective-method-functions, which are the functions which
  308.      actually call methods.  Every method referred to by aan 
  309.      effective-method-function is an applicable method as determined by
  310.      COMPUTE-APPLICABLE-METHODS (or maybe -USING-CLASSES or 
  311.      -USING-TYPES).  See the file combin.lisp.
  312.   to create secondary dispatch functions.  These functions are called by
  313.      discriminator functions when the dfun couldn't determine the set of
  314.      applicable methods (when EQL specializers are present), and are
  315.      actually discriminator functions in themselves sometimes (these 
  316.      are called dispatch dfuns).  See the file methods.lisp.
  317.